package br.com.unijui;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.view.JasperViewer;

/**
 *
 * @author Calebe Arruda
 * @version 1.01
 */
public class TestaNumerosPrimos extends javax.swing.JFrame {

    private int qtd;
    private int intervalo;
    private int numeroTeste;
    private int resultadoTestePrimo;
    private long tempoInicial;
    private long tempoFinal;
    private long tempoMedia;
    private long tempoSoma;
    public ArrayList<Integer> listaPrimos;
    private ArrayList<Long> listaTempoTestePrimos;
    private ArrayList<Byte> listaNumeroBits;
    private HashMap hashMapPrimos;
    private HashMap hashMapTempo;
    private HashMap hashMapBits;
    private ArrayList listaJasper;

    /**
     * Creates new form TestaNumerosPrimos
     */
    public TestaNumerosPrimos() {
        listaPrimos = new ArrayList<Integer>();
        listaNumeroBits = new ArrayList<Byte>();
        listaTempoTestePrimos = new ArrayList<Long>();
        hashMapPrimos = new HashMap();
        hashMapTempo = new HashMap();
        hashMapBits = new HashMap();
        listaJasper = new ArrayList();
        initComponents();
    }

    /**
     * Método para testar se o número é primo ou não
     *
     * @param numero a ser testado
     * @return true caso tenha 2 divisores com resto 0
     */
    public boolean testaPrimos(int numero, int numeroTestes) {
        int div = 0;

        for (int j = 0; j < numeroTestes; j++) {
            for (int i = 1; i <= numero; i++) {
                if ((numero % i) == 0 && j == 1) {
                    div++;
                }
            }
        }
        return (div == 2);
    }

    /**
     * Método para gerar Numeros Primos O Crivo de Eratóstenes é um algoritmo e
     * um método simples e prático para encontrar números primos até um certo
     * valor limite.
     */
    public void gerarNumerosPrimos() {
        qtd = new Integer(jTextField_qtdGerada.getText());
        intervalo = new Integer(jTextField_intervalo.getText());
        numeroTeste = new Integer(jTextField_NumeroTestes.getText());

        for (int i = 2; i <= qtd; i++) {
            listaPrimos.add(i);
        }

        for (int i = 0; i < listaPrimos.size(); i++) {
            for (int j = 1; j < listaPrimos.size(); j++) {
                resultadoTestePrimo = listaPrimos.get(j) % listaPrimos.get(i);
                if (resultadoTestePrimo == 0 && listaPrimos.get(j) != listaPrimos.get(i)) {
                    listaPrimos.remove(j);
                }
            }
        }

        for (int i = 0; i < listaPrimos.size(); i++) {
            int contadorIntervalo = 1;
            if (intervalo != 1 && intervalo != 0) {
                while (contadorIntervalo <= intervalo) {
                    if (listaPrimos.size() == i + 1) {
                        break;
                    }
                    listaPrimos.remove(i + 1);
                    contadorIntervalo += 1;
                }
            }
        }
        calcularMediaTempo();
        imprimir();
    }

    /**
     * Método para Calcular a Media do Tempo
     */
    public void calcularMediaTempo() {

        for (int i = 0; i < listaPrimos.size(); i++) {
            tempoInicial = System.nanoTime();
            if (testaPrimos(listaPrimos.get(i), numeroTeste)) {
                tempoFinal = System.nanoTime();
                tempoSoma = tempoFinal - tempoInicial;
                tempoMedia = tempoSoma / numeroTeste;

                listaTempoTestePrimos.add(tempoMedia);
                
                listaNumeroBits.add(new Byte((byte) ((listaPrimos.get(i).toBinaryString(listaPrimos.get(i))).length())));
            }
        }
    }

    /**
     * Método para imprimir o relatório
     */
    public void imprimir() {
        new Thread(new Runnable() {
            @Override
            public void run() {

                for (int i = 0; i < listaPrimos.size(); i++) {

                    Primo primo = new Primo();
                    primo.setQtdGerado(qtd);
                    primo.setIntervalo(intervalo);
                    primo.setQtdTestes(numeroTeste);
                    primo.setPrimo(listaPrimos.get(i));
                    primo.setTempo(listaTempoTestePrimos.get(i));
                    primo.setBits(listaNumeroBits.get(i));

                    listaJasper.add(primo);
                }

                //Montando o Bean Collection Data Source para o iReport fazer o relatorio
                JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(listaJasper);
                // Parametros do relatorios  
                Map parameters = new HashMap();

                try {

                    String layout = new File(getClass().getResource("relatorioComplexidade.jrxml").getFile()).getAbsolutePath();

                    //Gerando o jasper design  
                    JasperDesign desenho = JRXmlLoader.load(layout);

                    //Compila o relatório  
                    JasperReport relatorio = JasperCompileManager.compileReport(desenho);

                    //Imprimindo o relatorio
                    JasperPrint print = JasperFillManager.fillReport(relatorio, null, new JRBeanCollectionDataSource(listaJasper));

                    //Mostrando o relatorio na Tela
                    JasperViewer viewer = new JasperViewer(print);
                    viewer.setVisible(true);

                } catch (JRException e) {
                    System.out.println(e.getMessage());
                    System.out.println("PRINTSTACKTRACE = ");
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jTextField_qtdGerada = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        jTextField_intervalo = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jTextField_NumeroTestes = new javax.swing.JTextField();
        jPanel2 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        jPanel4 = new javax.swing.JPanel();
        jButton_gerar = new javax.swing.JButton();
        jButton_fechar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Números Primos");
        setPreferredSize(new java.awt.Dimension(400, 400));

        jLabel1.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N
        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel1.setText("Números Primos");
        jLabel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        getContentPane().add(jLabel1, java.awt.BorderLayout.PAGE_START);

        jPanel1.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 5, 15));

        jLabel2.setText("Quantidade a ser gerada: ");
        jLabel2.setPreferredSize(new java.awt.Dimension(150, 30));
        jPanel1.add(jLabel2);

        jTextField_qtdGerada.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        jTextField_qtdGerada.setPreferredSize(new java.awt.Dimension(100, 30));
        jPanel1.add(jTextField_qtdGerada);

        jLabel4.setText("Intervalo entre o números:");
        jLabel4.setPreferredSize(new java.awt.Dimension(150, 30));
        jPanel1.add(jLabel4);

        jTextField_intervalo.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        jTextField_intervalo.setPreferredSize(new java.awt.Dimension(100, 30));
        jPanel1.add(jTextField_intervalo);

        jLabel5.setText("Número de testes:");
        jLabel5.setPreferredSize(new java.awt.Dimension(150, 30));
        jPanel1.add(jLabel5);

        jTextField_NumeroTestes.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        jTextField_NumeroTestes.setPreferredSize(new java.awt.Dimension(100, 30));
        jPanel1.add(jTextField_NumeroTestes);

        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

        jPanel2.setPreferredSize(new java.awt.Dimension(15, 267));

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 15, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 167, Short.MAX_VALUE)
        );

        getContentPane().add(jPanel2, java.awt.BorderLayout.LINE_START);

        jPanel3.setPreferredSize(new java.awt.Dimension(15, 267));

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 15, Short.MAX_VALUE)
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 167, Short.MAX_VALUE)
        );

        getContentPane().add(jPanel3, java.awt.BorderLayout.LINE_END);

        jButton_gerar.setText("Gerar");
        jButton_gerar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton_gerarActionPerformed(evt);
            }
        });

        jButton_fechar.setText("Fechar");
        jButton_fechar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton_fecharActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
                .addContainerGap(296, Short.MAX_VALUE)
                .addComponent(jButton_gerar)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jButton_fechar)
                .addContainerGap())
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
                .addContainerGap(66, Short.MAX_VALUE)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton_gerar)
                    .addComponent(jButton_fechar))
                .addContainerGap())
        );

        getContentPane().add(jPanel4, java.awt.BorderLayout.PAGE_END);

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>//GEN-END:initComponents

    private void jButton_gerarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton_gerarActionPerformed
        gerarNumerosPrimos();
    }//GEN-LAST:event_jButton_gerarActionPerformed

    private void jButton_fecharActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton_fecharActionPerformed
        this.dispose();
    }//GEN-LAST:event_jButton_fecharActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(TestaNumerosPrimos.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(TestaNumerosPrimos.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(TestaNumerosPrimos.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(TestaNumerosPrimos.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new TestaNumerosPrimos().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton_fechar;
    private javax.swing.JButton jButton_gerar;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JTextField jTextField_NumeroTestes;
    private javax.swing.JTextField jTextField_intervalo;
    private javax.swing.JTextField jTextField_qtdGerada;
    // End of variables declaration//GEN-END:variables
}
